// 依赖收集器
class Dep {
  constructor () {
    this.sub = {}
  }
  addSub (key) {
    if(this.sub[key]) {
      this.sub[key].push(Dep.target)
      return
    }
    this.sub[key] = [Dep.target]
  }
  notify (key) {
    if (this.sub[key]) {
      for (let fn of this.sub[key]) {
        fn()
      }
    }
  }
}

Dep.target = null
function pushTarget(watch){
  Dep.target = watch
}

function popTarget () {
  Dep.target = null
}

function reactive (obj) {
  const dep = new Dep()

  return new Proxy(obj, {
    get (target, key) {
      // 收集针对此属性的依赖
      if (Dep.target) {
        dep.addSub(key)
      }
      return Reflect.get(target, key)
    },
    set (target, key, value) {
      Reflect.set(target, key, value)
      // 触发此属性的依赖
      dep.notify(key)
    }
  })
}

function watch (effect) {
  // 存储当前依赖
  pushTarget(effect)
  // 触发回调内部成员的get方法
  effect()
  // 收集完后移除依赖
  popTarget()
}

const state = reactive({
  foo: 100,
  bar: 200
})

watch(() => {
  console.log('foo change1', state.foo)
})

watch(() => {
  console.log('foo change2', state.foo)
})

watch(() => {
  console.log('bar change1', state.bar)
})

watch(() => {
  console.log('bar change2', state.bar)
})

state.foo++
state.bar++
